package com.wyd.component.netty;

import com.wyd.component.netty.constants.Constants;
import com.wyd.component.netty.handler.BizHandler;
import com.wyd.component.netty.handler.HeartBeatHandler;
import com.wyd.component.netty.handler.MsgConvertHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;

@Slf4j
public class DeviceServer {

    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private ServerBootstrap boot;
    private Channel channel;

    public DeviceServer(int bossThread, int workThread) {
        bossGroup = new NioEventLoopGroup(bossThread);
        workerGroup = new NioEventLoopGroup(workThread);
        boot = new ServerBootstrap();
        boot.group(bossGroup, workerGroup);
    }

    public void start(int port) {
        try {
            boot.channel(NioServerSocketChannel.class);
            boot.option(ChannelOption.SO_BACKLOG, 1024);
            boot.option(ChannelOption.SO_SNDBUF, 1048576);// 128k发送缓冲区
            boot.option(ChannelOption.SO_RCVBUF, 1048576);// 接收缓冲区
            boot.childHandler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel ch) throws Exception {
                    ByteBuf byteBuf = Unpooled.copiedBuffer(Constants.DELIMITER.getBytes("utf-8"));
                    DelimiterBasedFrameDecoder decoder = new DelimiterBasedFrameDecoder(1024, byteBuf);
                    ch.pipeline().addLast("DelimiterBasedFrameDecoder", decoder);
                    // 将分隔之后的字节数据转换为字符串数据
                    ch.pipeline().addLast("IdleStateHandler", new IdleStateHandler(120, 120, 130));
                    ch.pipeline().addLast("HeartBeatHandler", new HeartBeatHandler());
                    ch.pipeline().addLast("StringDecoder", new StringDecoder(Charset.forName("utf-8")));//
                    ch.pipeline().addLast("StringEncoder", new StringEncoder(Charset.forName("utf-8")));
                    ch.pipeline().addLast("MsgConvertHandler", new MsgConvertHandler());
                    ch.pipeline().addLast("BizHandler", new BizHandler());
                }
            });
            ChannelFuture bind = boot.bind(port).sync();
            channel=bind.channel();
            log.info("=================SOCKET bind :{} port success",port);
            channel.closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            log.info("BoxServer close :{}", "Server stop end");
            try {
                bossGroup.shutdownGracefully();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                workerGroup.shutdownGracefully();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void stopServer(){
        try {
            channel.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
